package heap

import "hi-jvm/classfile"
/*
字段符号引用
 */
type FieldRef struct {
	MemberRef
	Field *Field
}

func newFieldRef(cp *ConstantPool, refInfo *classfile.ConstantFieldrefInfo) *FieldRef {
	ref := &FieldRef{}
	ref.Cp = cp
	ref.copyMemberRefInfo(&refInfo.ConstantMemberrefInfo)
	return ref
}

/**
字段符号引用解析
*/
func (self *FieldRef) ResolvedField() *Field {
	if self.Field == nil {
		self.resolveFieldRef()
	}
	return self.Field
}

/**
字段符号引用解析
如果类D想通过字段符号引用访问类C的某个字段
首先要解析符号引用得到类C
然后根据字段名和描述符查找字段，
	如果查找失败，则抛出异常
	如果成功，但D没有足够权限，则抛出异常
 */
// jvms 5.4.3.2
func (self *FieldRef) resolveFieldRef() {
	d := self.Cp.Class
	c := self.ResolvedClass()
	field := lookupField(c, self)

	if field == nil {
		panic("java.lang.NoSuchFieldError")
	}
	if !field.isAccessibleTo(d) {
		panic("java.lang.IllegalAccessError")
	}

	self.Field = field
}

/*
首先在C的字段中查找，如果找不到，在C的直接接口递归查找
 */
func lookupField(c *Class, compare *FieldRef) *Field {
	for _, field := range c.Fields {
		if field.isMine(compare) {
			return field
		}
	}

	for _, iface := range c.Interfaces {
		field := lookupField(iface, compare);
		if field != nil {
			return field
		}
	}

	if c.SuperClass != nil {
		return lookupField(c.SuperClass, compare)
	}

	return nil
}

